/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MainFrame.java
 *
 * Created on Apr 2, 2011, 2:12:17 PM
 */
package edu.usc.cs576.mediaoctopus;

import edu.usc.cs576.lib.Action;
import edu.usc.cs576.lib.MediaFactory;
import edu.usc.cs576.lib.MediaObject;
import edu.usc.cs576.lib.Monitor.LoadingMonitor;
import edu.usc.cs576.lib.mediaObject.Audio;
import edu.usc.cs576.lib.mediaObject.Image;
import edu.usc.cs576.lib.mediaObject.KeyFrame;
import edu.usc.cs576.lib.mediaObject.Track;
import edu.usc.cs576.lib.mediaObject.Video;
import edu.usc.cs576.lib.xml.XMLWriter;
import edu.usc.cs576.mediaoctopus.config.Settings;
import edu.usc.cs576.mediaoctopus.data.Data;
import edu.usc.cs576.mediaoctopus.panels.AddDisplayActionPanel;
import edu.usc.cs576.mediaoctopus.panels.AddLinkActionPanel;
import edu.usc.cs576.mediaoctopus.panels.CanvasConfig;
import edu.usc.cs576.mediaoctopus.panels.ImportDialog;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingWorker;

/**
 *
 * @author haoxu
 */
public class MainFrame extends javax.swing.JFrame {

    /** Creates new form MainFrame */
    public MainFrame() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainFileChooser = new javax.swing.JFileChooser();
        videoFileChooser = new javax.swing.JFileChooser();
        audioFileChooser = new javax.swing.JFileChooser();
        imageFileChooser = new javax.swing.JFileChooser();
        publishFile = new javax.swing.JFileChooser();
        jPanel1 = new javax.swing.JPanel();
        infoPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        libraryList = new javax.swing.JList();
        jLabel1 = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        actionList = new javax.swing.JList();
        publishButton = new javax.swing.JButton();
        addPlayActionButton = new javax.swing.JButton();
        addPauseActionButton = new javax.swing.JButton();
        addLinkActionButton = new javax.swing.JButton();
        addDisplayActionButton = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JSeparator();
        jSeparator5 = new javax.swing.JSeparator();
        jLabel3 = new javax.swing.JLabel();
        frameNumTextField = new javax.swing.JTextField();
        fpsTextField = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        framePlayButton = new javax.swing.JButton();
        framePauseButton = new javax.swing.JButton();
        frameStopButton = new javax.swing.JButton();
        addStopActionButton = new javax.swing.JButton();
        removeActionButton = new javax.swing.JButton();
        selected = new javax.swing.JLabel();
        controlPanel = new javax.swing.JPanel();
        timeline = new javax.swing.JSlider();
        canvasBack = new javax.swing.JPanel();
        canvasPanel = new javax.swing.JPanel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        newJMenuItem = new javax.swing.JMenuItem();
        openJMenuItem = new javax.swing.JMenuItem();
        saveJMenuItem = new javax.swing.JMenuItem();
        jSeparator4 = new javax.swing.JPopupMenu.Separator();
        exitJMenuItem = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenu4 = new javax.swing.JMenu();
        insertVideoJMenuItem = new javax.swing.JMenuItem();
        insertAudioJMenuItem = new javax.swing.JMenuItem();
        insertImageJMenuItem = new javax.swing.JMenuItem();
        insertTTrackAreaJMenuItem = new javax.swing.JMenuItem();
        canvasjMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        infoPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        infoPanel.setMaximumSize(new java.awt.Dimension(173, 32767));
        infoPanel.setMinimumSize(new java.awt.Dimension(173, 100));

        libraryList.setModel(new DefaultListModel());
        jScrollPane1.setViewportView(libraryList);

        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Library");

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel2.setText("Actions:");

        actionList.setModel(new DefaultListModel());
        jScrollPane2.setViewportView(actionList);

        publishButton.setText("Publish");
        publishButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                publishButtonActionPerformed(evt);
            }
        });

        addPlayActionButton.setText("Play");
        addPlayActionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addPlayActionButtonActionPerformed(evt);
            }
        });

        addPauseActionButton.setText("Pause");
        addPauseActionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addPauseActionButtonActionPerformed(evt);
            }
        });

        addLinkActionButton.setText("Link");
        addLinkActionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addLinkActionButtonActionPerformed(evt);
            }
        });

        addDisplayActionButton.setText("Display");
        addDisplayActionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addDisplayActionButtonActionPerformed(evt);
            }
        });

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel3.setText("Frame Control");

        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel4.setText("Frame");

        jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel5.setText("FPS");

        framePlayButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/usc/cs576/mediaoctopus/resources/CornerStone_023.png"))); // NOI18N
        framePlayButton.setToolTipText("Play");
        framePlayButton.setMaximumSize(new java.awt.Dimension(30, 30));
        framePlayButton.setPreferredSize(new java.awt.Dimension(30, 30));
        framePlayButton.setSize(new java.awt.Dimension(30, 30));
        framePlayButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                framePlayButtonActionPerformed(evt);
            }
        });

        framePauseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/usc/cs576/mediaoctopus/resources/CornerStone_021.png"))); // NOI18N
        framePauseButton.setToolTipText("Pause");
        framePauseButton.setMaximumSize(new java.awt.Dimension(30, 30));
        framePauseButton.setPreferredSize(new java.awt.Dimension(30, 30));
        framePauseButton.setSize(new java.awt.Dimension(30, 30));
        framePauseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                framePauseButtonActionPerformed(evt);
            }
        });

        frameStopButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/usc/cs576/mediaoctopus/resources/CornerStone_039.png"))); // NOI18N
        frameStopButton.setToolTipText("Stop");
        frameStopButton.setMaximumSize(new java.awt.Dimension(30, 30));
        frameStopButton.setPreferredSize(new java.awt.Dimension(30, 30));
        frameStopButton.setSize(new java.awt.Dimension(30, 30));
        frameStopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                frameStopButtonActionPerformed(evt);
            }
        });

        addStopActionButton.setText("Stop");
        addStopActionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addStopActionButtonActionPerformed(evt);
            }
        });

        removeActionButton.setText("Remove");
        removeActionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeActionButtonActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout infoPanelLayout = new org.jdesktop.layout.GroupLayout(infoPanel);
        infoPanel.setLayout(infoPanelLayout);
        infoPanelLayout.setHorizontalGroup(
            infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jLabel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(jSeparator1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(infoPanelLayout.createSequentialGroup()
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(addPlayActionButton, 0, 0, Short.MAX_VALUE)
                    .add(addLinkActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 72, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(addDisplayActionButton, 0, 0, Short.MAX_VALUE)
                    .add(addPauseActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 72, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(removeActionButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(addStopActionButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 93, Short.MAX_VALUE)))
            .add(jSeparator2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(jLabel3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(infoPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jLabel4)
                    .add(jLabel5))
                .add(22, 22, 22)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(fpsTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)
                    .add(frameNumTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE))
                .addContainerGap())
            .add(infoPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(framePlayButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(framePauseButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(frameStopButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(132, Short.MAX_VALUE))
            .add(jSeparator5, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(infoPanelLayout.createSequentialGroup()
                .add(jLabel2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 67, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(selected, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE)
                .addContainerGap())
            .add(publishButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
            .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
        );
        infoPanelLayout.setVerticalGroup(
            infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(infoPanelLayout.createSequentialGroup()
                .add(jLabel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 16, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(10, 10, 10)
                .add(jSeparator1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel2)
                    .add(selected, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 16, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 79, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(7, 7, 7)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(addPlayActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(addPauseActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(addStopActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(addLinkActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                        .add(addDisplayActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(removeActionButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jSeparator2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jLabel3)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(frameNumTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel4))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel5)
                    .add(fpsTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE))
                .add(29, 29, 29)
                .add(infoPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(framePlayButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(framePauseButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(frameStopButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jSeparator5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(publishButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(42, 42, 42))
        );

        controlPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        timeline.setMajorTickSpacing(180);
        timeline.setMaximum(1800);
        timeline.setMinorTickSpacing(18);
        timeline.setPaintLabels(true);
        timeline.setPaintTicks(true);
        timeline.setToolTipText("timeline");
        timeline.setValue(0);
        timeline.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                timelineStateChanged(evt);
            }
        });

        org.jdesktop.layout.GroupLayout controlPanelLayout = new org.jdesktop.layout.GroupLayout(controlPanel);
        controlPanel.setLayout(controlPanelLayout);
        controlPanelLayout.setHorizontalGroup(
            controlPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 928, Short.MAX_VALUE)
            .add(controlPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(org.jdesktop.layout.GroupLayout.TRAILING, timeline, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 928, Short.MAX_VALUE))
        );
        controlPanelLayout.setVerticalGroup(
            controlPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 56, Short.MAX_VALUE)
            .add(controlPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(timeline, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 56, Short.MAX_VALUE))
        );

        canvasBack.setLayout(new java.awt.GridBagLayout());

        canvasPanel.setBackground(new java.awt.Color(102, 102, 102));
        canvasPanel.setPreferredSize(new java.awt.Dimension(528, 432));
        canvasPanel.setSize(new java.awt.Dimension(528, 432));
        canvasPanel.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                canvasPanelMouseMoved(evt);
            }
        });

        org.jdesktop.layout.GroupLayout canvasPanelLayout = new org.jdesktop.layout.GroupLayout(canvasPanel);
        canvasPanel.setLayout(canvasPanelLayout);
        canvasPanelLayout.setHorizontalGroup(
            canvasPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 528, Short.MAX_VALUE)
        );
        canvasPanelLayout.setVerticalGroup(
            canvasPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 432, Short.MAX_VALUE)
        );

        canvasBack.add(canvasPanel, new java.awt.GridBagConstraints());

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .add(infoPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(controlPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(canvasBack, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 932, Short.MAX_VALUE)))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
                .add(canvasBack, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 625, Short.MAX_VALUE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(controlPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
            .add(infoPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        jMenu1.setText("File");

        newJMenuItem.setText("New");
        newJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newJMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(newJMenuItem);

        openJMenuItem.setText("Open");
        openJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openJMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(openJMenuItem);

        saveJMenuItem.setText("Save");
        saveJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveJMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(saveJMenuItem);
        jMenu1.add(jSeparator4);

        exitJMenuItem.setText("Exit");
        exitJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitJMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(exitJMenuItem);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");

        jMenu4.setText("Insert");

        insertVideoJMenuItem.setText("Video");
        insertVideoJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importVideoJMenuItemActionPerformed(evt);
            }
        });
        jMenu4.add(insertVideoJMenuItem);

        insertAudioJMenuItem.setText("Audio");
        insertAudioJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importAudioJMenuItemActionPerformed(evt);
            }
        });
        jMenu4.add(insertAudioJMenuItem);

        insertImageJMenuItem.setText("Image");
        insertImageJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importImageJMenuItemActionPerformed(evt);
            }
        });
        jMenu4.add(insertImageJMenuItem);

        insertTTrackAreaJMenuItem.setText("Track Area");
        insertTTrackAreaJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                insertTTrackAreaJMenuItemActionPerformed(evt);
            }
        });
        jMenu4.add(insertTTrackAreaJMenuItem);

        jMenu2.add(jMenu4);

        canvasjMenuItem.setText("Canvas");
        canvasjMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                canvasjMenuItemActionPerformed(evt);
            }
        });
        jMenu2.add(canvasjMenuItem);

        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void newJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newJMenuItemActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_newJMenuItemActionPerformed

    private void openJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openJMenuItemActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_openJMenuItemActionPerformed

    private void saveJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveJMenuItemActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_saveJMenuItemActionPerformed

    private void exitJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitJMenuItemActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_exitJMenuItemActionPerformed

    private void importVideoJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importVideoJMenuItemActionPerformed
        // TODO add your handling code here:

        int returnVal = videoFileChooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {

            File file = videoFileChooser.getSelectedFile();

            importVideoDialog = new ImportDialog(this, true);

            importVideoDialog.getTitleLabel().setText("Import Video From " + file.getName());
            importVideoDialog.setTitle("Import Video");

            ImportVideoTask ivtask = new ImportVideoTask();
            ivtask.setFilaname(file.getName());
            ivtask.setFilepath(file.getAbsolutePath());
            ivtask.addPropertyChangeListener(importVideoDialog);
            new Thread() {

                @Override
                public void run() {
                    importVideoDialog.setVisible(true);
                }
            }.start();
            ivtask.execute();
        }
    }//GEN-LAST:event_importVideoJMenuItemActionPerformed

    private void importAudioJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importAudioJMenuItemActionPerformed
        // TODO add your handling code here:
        // TODO add your handling code here:

        int returnVal = audioFileChooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = audioFileChooser.getSelectedFile();
            ImportAudioTask autask = new ImportAudioTask();
            autask.setFilaname(file.getName());
            autask.setFilepath(file.getAbsolutePath());
            try {
                autask.doInBackground();
                autask.done();
            } catch (Exception ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            }

//System.out.println("aaaaaaaaaaaaaa");
            new Thread() {

                @Override
                public void run() {
                    //  importAudioDialog.setVisible(true);
                    //   Audio audio = MediaFactory.getInstance().readAudio(file.getAbsolutePath(), file.getName(), Settings.AUDIO_TYPE_WAV);
                    //  Data.setAudio(audio);
                }
            }.start();
        }
    }//GEN-LAST:event_importAudioJMenuItemActionPerformed

    private void importImageJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importImageJMenuItemActionPerformed
        // TODO add your handling code here:
        int returnVal = imageFileChooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {

            new Thread() {

                @Override
                public void run() {
                    File file = imageFileChooser.getSelectedFile();
                    Image image = MediaFactory.getInstance().readImage(file.getAbsolutePath());
                    image.setFilename(file.getName());
                    Data.getImages().add(image);

                    image.setFilename(file.getName());
                    image.setFilepath(file.getAbsolutePath());
                    image.setWidth(Settings.IMAGE_DEFAULT_WIDTH);
                    image.setHeight(Settings.IMAGE_DEFAULT_HEIGHT);
                    image.load();

                    ((DefaultListModel) (libraryList.getModel())).addElement(file.getName());

                    Settings.IS_IMAGE_IMPORTED = true;

                    ImageIcon icon = new ImageIcon(image.getImage());
                    JLabel imageLabel = new JLabel();
                    //for test, add border
                    imageLabel.setBorder(BorderFactory.createLineBorder(Color.black));
                    imageLabel.setIcon(icon);
                    imageLabel.setSize(new Dimension(Settings.IMAGE_DEFAULT_WIDTH, Settings.IMAGE_DEFAULT_HEIGHT));
                    imageLabel.addMouseMotionListener(new MouseMotionListener() {

                        public void mouseDragged(MouseEvent me) {
                            labelDragged(me);
                        }

                        public void mouseMoved(MouseEvent me) {
                            labelMoved(me);
                        }
                    });
                    imageLabel.addMouseListener(new MouseListener() {

                        public void mouseClicked(MouseEvent me) {
                            labelClicked(me);
                        }

                        public void mousePressed(MouseEvent me) {
                        }

                        public void mouseReleased(MouseEvent me) {
                            labelReleased(me);
                        }

                        public void mouseEntered(MouseEvent me) {
                        }

                        public void mouseExited(MouseEvent me) {
                        }
                    });

                    Data.getDisplay().put(image, imageLabel);
                    Data.getData().put(imageLabel, image);

                    canvasPanel.add(imageLabel);
                    canvasPanel.setComponentZOrder(imageLabel, 0);
                    canvasPanel.validate();
                    canvasPanel.repaint();
                }
            }.start();
        }
    }//GEN-LAST:event_importImageJMenuItemActionPerformed

    private void insertTTrackAreaJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_insertTTrackAreaJMenuItemActionPerformed
        // TODO add your handling code here:
        Track track = new Track();
        track.setWidth(150);
        track.setHeight(150);

        KeyFrame keyframe1 = new KeyFrame();
        KeyFrame keyframe2 = new KeyFrame();

        keyframe1.setFrameNum(Settings.FRAME_NUM);
        keyframe2.setFrameNum(Settings.TOTAL_FRAME_NUM);

        track.addKeyFrame(keyframe1);
        track.addKeyFrame(keyframe2);

        JLabel trackLabel = new JLabel();
        trackLabel.setBorder(BorderFactory.createLineBorder(new Color(255, 0, 0), 2));
        trackLabel.addMouseMotionListener(new MouseMotionListener() {

            public void mouseDragged(MouseEvent e) {
                labelDragged(e);
            }

            public void mouseMoved(MouseEvent e) {
                labelMoved(e);
            }
        });
        trackLabel.addMouseListener(new MouseListener() {

            public void mouseClicked(MouseEvent e) {
                labelClicked(e);
            }

            public void mousePressed(MouseEvent e) {
            }

            public void mouseReleased(MouseEvent e) {
                labelReleased(e);
            }

            public void mouseEntered(MouseEvent e) {
            }

            public void mouseExited(MouseEvent e) {
            }
        });

        canvasPanel.add(trackLabel);
        canvasPanel.setComponentZOrder(trackLabel, 0);
        trackLabel.setLocation(0, 0);
        trackLabel.setSize(new Dimension(150, 150));

        track.setStartFrame(Settings.FRAME_NUM);
        track.setEndFrame(Settings.TOTAL_FRAME_NUM);
        track.setName("track" + Data.getTracks().size() + 1);

        Data.getData().put(trackLabel, track);
        Data.getDisplay().put(track, trackLabel);

        Data.getTracks().add(track);
    }//GEN-LAST:event_insertTTrackAreaJMenuItemActionPerformed

    private void publishButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_publishButtonActionPerformed
        // TODO add your handling code here:
        int returnVal = publishFile.showSaveDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {

            File file = publishFile.getSelectedFile();
            XMLWriter writer = new XMLWriter(file.getName(), file.getAbsolutePath());
            writer.initial();

            writer.writeSize(Settings.CANVAS_WIDTH, Settings.CANVAS_HEIGHT);

            if (Data.getVideo() != null) {
                writer.write(Data.getVideo(), Data.getDisplay().get(Data.getVideo()));
            }

            if (Data.getAudio() != null) {
                writer.write(Data.getAudio());
            }

            for (int i = 0; i < Data.getImages().size(); i++) {
                Image image = Data.getImages().get(i);
                writer.write(image, Data.getDisplay().get(image));
            }

            for (int i = 0; i < Data.getTracks().size(); i++) {
                Track track = Data.getTracks().get(i);
                writer.write(track, Data.getDisplay().get(track));
            }

            writer.close();
        }
    }//GEN-LAST:event_publishButtonActionPerformed

    private void framePlayButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_framePlayButtonActionPerformed
        // TODO add your handling code here:
        if (!Settings.IS_PLAYING) {
            //play video
            if (Settings.IS_VIDEO_IMPORTED) {
                System.out.println("video import!");
                Settings.IS_PLAYING = true;
                Settings.IS_STOPPED = false;
                Settings.IS_PAUSED = true;
                FrameUpdateThread fut = new FrameUpdateThread();
                fut.start();
            }

            //play audio
            if (Settings.IS_AUDIO_IMPORTED) {
                Settings.IS_PLAYING = true;
                Settings.IS_STOPPED = false;
                Settings.IS_PAUSED = false;
                System.out.println("Audio import!");
                new Thread() {

                    @Override
                    public void run() {
                        //Data.getAudio().load();
                        Data.getAudio().show();
//                        if (!Settings.IS_VIDEO_IMPORTED) {
//                          //  timeline.setValue();
//
//                        }
                    }
                }.start();
                if (!Settings.IS_VIDEO_IMPORTED) {
                    new Thread() {

                        @Override
                        public void run() {
                            while (Settings.IS_PLAYING) {
                                //  System.out.println( Data.getAudio().getPos());
                                if (Data.getAudio().getPos() < Data.getAudio().getf()) {
                                    // System.out.println(Data.getAudio().getPos());
                                    timeline.setValue(Data.getAudio().getPos() / 1000);
                                }
                            }
//                        }
                        }
                    }.start();
                } else {
                    new Thread() {

                        boolean ispau = false;

                        @Override
                        public void run() {
                            while (Settings.IS_PLAYING) {
                                double rate = (double) Data.getAudio().getf() / (double) Data.getVideo().getImages().size();
                                double real_rate = (double) Data.getAudio().getPos() / (double) Settings.FRAME_NUM;
                                System.out.println("rate : " + rate);
                                System.out.println("real_rate : " + real_rate);
                                if (real_rate / rate > 1.002 && ispau == false) {
                                    System.out.println("1111111rate : " + rate);
                                    System.out.println("1111111real_rate : " + real_rate);
                                    Data.getAudio().pause();
                                    ispau = true;
                                } else if (real_rate / rate <= 1.001 && ispau == true) {
                                    System.out.println("22222222rate : " + rate);
                                    System.out.println("22222222real_rate : " + real_rate);
                                    Data.getAudio().show();
                                    ispau = false;
                                }
                            }
                        }
                    }.start();
                }
            }
        } else if (Settings.IS_PLAYING) {
            Settings.IS_PLAYING = true;
            Settings.IS_STOPPED = false;
            Settings.IS_PAUSED = false;
            new Thread() {

                @Override
                public void run() {
                    if (Settings.IS_AUDIO_IMPORTED) {
                        Data.getAudio().set();
                        Data.getAudio().show();
                    }
//                    if (Settings.IS_VIDEO_IMPORTED) {
//                        FrameUpdateThread fut = new FrameUpdateThread();
//                        fut.start();
//                    }
                }
            }.start();
        }

    }//GEN-LAST:event_framePlayButtonActionPerformed
    private void framePauseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_framePauseButtonActionPerformed
        // TODO add your handling code here:
        if (Settings.IS_PLAYING) {
            System.out.println("is playing");
            Settings.IS_PLAYING = false;
            Settings.IS_PAUSED = true;
            Settings.IS_STOPPED = false;
            if (Settings.IS_AUDIO_IMPORTED) {
                Data.getAudio().pause();
            }
//             if (Settings.IS_AUDIO_IMPORTED){
//             Data.getAudio().pause();
            //  }
//            playtimer.stop();
        } else {
            System.out.println("isnot playing");
            Settings.IS_PLAYING = true;
            Settings.IS_PAUSED = false;
            Settings.IS_STOPPED = false;

//            playtimer.start();
        }
    }//GEN-LAST:event_framePauseButtonActionPerformed

    private void frameStopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_frameStopButtonActionPerformed
        // TODO add your handling code here:
        if (Settings.IS_PLAYING) {
            Settings.IS_PLAYING = false;
            Settings.IS_STOPPED = true;
            if (Settings.IS_AUDIO_IMPORTED) {
                Data.getAudio().stop();
            }
        }
    }//GEN-LAST:event_frameStopButtonActionPerformed

    private void timelineStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_timelineStateChanged
        // TODO add your handling code here:
        JSlider source = (JSlider) evt.getSource();
        if (!source.getValueIsAdjusting() && Settings.IS_VIDEO_IMPORTED) {
            if (Settings.IS_PLAYING) {
                Settings.FRAME_NUM = (int) source.getValue();
            } else {
                Settings.FRAME_NUM = (int) source.getValue();
                updateFrame();
            }
        }
    }//GEN-LAST:event_timelineStateChanged

    private void canvasPanelMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_canvasPanelMouseMoved
        // TODO add your handling code here:
        JPanel panel = (JPanel) evt.getSource();
        panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        resizeOperation = false;
    }//GEN-LAST:event_canvasPanelMouseMoved

    private void canvasjMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_canvasjMenuItemActionPerformed
        // TODO add your handling code here:
        CanvasConfig config = new CanvasConfig(this, true, canvasPanel);
        config.setVisible(true);
    }//GEN-LAST:event_canvasjMenuItemActionPerformed

    private void addPlayActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addPlayActionButtonActionPerformed
        // TODO add your handling code here:
        if (selectedLabel == null) {
            JOptionPane.showMessageDialog(this, "You should select the media object first");
            return;
        }
        if (Data.getVideo() == null && Data.getAudio() == null) {
            JOptionPane.showMessageDialog(this, "You should import video or audio first");
        } else {
            if (Data.getVideo() != null) {
                Action action = new Action();
                action.setActionNumber(Settings.PLAY_VIDEO_ACTION);
                Data.getData().get(selectedLabel).getActions().add(action);
                ((DefaultListModel) (actionList.getModel())).addElement(action);
            }

            if (Data.getAudio() != null) {
                Action action = new Action();
                action.setActionNumber(Settings.PLAY_AUDIO_ACTION);
                Data.getData().get(selectedLabel).getActions().add(action);
                ((DefaultListModel) (actionList.getModel())).addElement(action);
            }
        }
    }//GEN-LAST:event_addPlayActionButtonActionPerformed

    private void addPauseActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addPauseActionButtonActionPerformed
        // TODO add your handling code here:
        if (selectedLabel == null) {
            JOptionPane.showMessageDialog(this, "You should select the media object first");
            return;
        }
        if (Data.getVideo() == null && Data.getAudio() == null) {
            JOptionPane.showMessageDialog(this, "You should import video or audio first");
        } else {
            if (Data.getVideo() != null) {
                Action action = new Action();
                action.setActionNumber(Settings.PAUSE_VIDEO_ACTION);
                Data.getData().get(selectedLabel).getActions().add(action);
                ((DefaultListModel) (actionList.getModel())).addElement(action);
            }

            if (Data.getAudio() != null) {
                Action action = new Action();
                action.setActionNumber(Settings.PAUSE_AUDIO_ACTION);
                Data.getData().get(selectedLabel).getActions().add(action);
                ((DefaultListModel) (actionList.getModel())).addElement(action);
            }
        }
    }//GEN-LAST:event_addPauseActionButtonActionPerformed

    private void addStopActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addStopActionButtonActionPerformed
        // TODO add your handling code here:
        if (selectedLabel == null) {
            JOptionPane.showMessageDialog(this, "You should select the media object first");
            return;
        }
        if (Data.getVideo() == null && Data.getAudio() == null) {
            JOptionPane.showMessageDialog(this, "You should import video or audio first");
        } else {
            if (Data.getVideo() != null) {
                Action action = new Action();
                action.setActionNumber(Settings.STOP_VIDEO_ACTION);
                Data.getData().get(selectedLabel).getActions().add(action);
                ((DefaultListModel) (actionList.getModel())).addElement(action);
            }

            if (Data.getAudio() != null) {
                Action action = new Action();
                action.setActionNumber(Settings.STOP_AUDIO_ACTION);
                Data.getData().get(selectedLabel).getActions().add(action);
                ((DefaultListModel) (actionList.getModel())).addElement(action);
            }
        }
    }//GEN-LAST:event_addStopActionButtonActionPerformed

    private void addLinkActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addLinkActionButtonActionPerformed
        // TODO add your handling code here:
        if (selectedLabel == null) {
            JOptionPane.showMessageDialog(this, "You should select the media object first");
            return;
        }
        AddLinkActionPanel linkActionPanel = new AddLinkActionPanel(this, true);
        Settings.actionFinished = false;
        linkActionPanel.setVisible(true);
        if (Settings.actionFinished) {
            Action action = new Action();
            action.setActionNumber(Settings.LINK_ACTION);
            action.setParam1(Settings.param);
            action.setSource(Data.getData().get(selectedLabel));
            ((DefaultListModel) (actionList.getModel())).addElement(action);

            Data.getData().get(selectedLabel).getActions().add(action);
        }
    }//GEN-LAST:event_addLinkActionButtonActionPerformed

    private void addDisplayActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addDisplayActionButtonActionPerformed
        // TODO add your handling code here:
        if (selectedLabel == null) {
            JOptionPane.showMessageDialog(this, "You should select the media object first");
            return;
        }
        AddDisplayActionPanel displayActionPanel = new AddDisplayActionPanel(this, true);
        Settings.actionFinished = false;
        displayActionPanel.setVisible(true);
        if (Settings.actionFinished) {
            Action action = new Action();
            action.setActionNumber(Settings.DISPLAY_ACTION);
            action.setParam1(Settings.param);
            action.setParam2(Settings.param2);
            action.setSource(Data.getData().get(selectedLabel));
            ((DefaultListModel) (actionList.getModel())).addElement(action);

            MediaObject object = Data.getData().get(selectedLabel);
            object.getActions().add(action);
            object.setStartFrame(Integer.parseInt(Settings.param));
            object.setEndFrame(Integer.parseInt(Settings.param2));

            if (object instanceof Track) {
                KeyFrame frame1 = new KeyFrame();
                KeyFrame frame2 = new KeyFrame();

                frame1.setFrameNum(Integer.parseInt(Settings.param));
                frame2.setFrameNum(Integer.parseInt(Settings.param2));

                Point point = ((Track) object).getLocation(Integer.parseInt(Settings.param));
                Point point2 = ((Track) object).getLocation(Integer.parseInt(Settings.param2));


                for (int i = 0; i < ((Track) object).getKeyframes().size(); i++) {
                    KeyFrame frame = ((Track) object).getKeyframes().get(i);
                    if (frame.getFrameNum() <= Integer.parseInt(Settings.param)) {
                        ((Track) object).getKeyframes().remove(frame);
                    } else if (frame.getFrameNum() >= Integer.parseInt(Settings.param2)) {
                        ((Track) object).getKeyframes().remove(frame);
                    }
                }

                if (((Track) object).getKeyframes().isEmpty()) {
                    frame1.setPosition_x(0);
                    frame1.setPosition_y(0);
                } else {
                    if (point == null) {
                        frame1.setPosition_x(((Track) object).getKeyframes().get(0).getPosition_x());
                        frame1.setPosition_y(((Track) object).getKeyframes().get(0).getPosition_y());
                    } else {
                        frame1.setPosition_x(point.x);
                        frame1.setPosition_y(point.y);
                    }

                    if (point2 == null) {
                        frame2.setPosition_x(((Track) object).getKeyframes().get(((Track) object).getKeyframes().size() - 1).getPosition_x());
                        frame2.setPosition_y(((Track) object).getKeyframes().get(((Track) object).getKeyframes().size() - 1).getPosition_y());
                    } else {
                        frame2.setPosition_x(point2.x);
                        frame2.setPosition_y(point2.y);
                    }
                }


                ((Track) object).getKeyframes().add(0, frame1);
                ((Track) object).getKeyframes().add(frame2);
            }
        }
    }//GEN-LAST:event_addDisplayActionButtonActionPerformed

    private void removeActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeActionButtonActionPerformed
        // TODO add your handling code here:
        Settings.selectedIndex = -1;
        Action action = (Action) ((DefaultListModel) (actionList.getModel())).get(actionList.getSelectedIndex());
        ArrayList actions = Data.getData().get(selectedLabel).getActions();

        for (int i = 0; i < actions.size(); i++) {
            if (actions.get(i).toString().equals(action.toString())) {
                actions.remove(i);
            }
        }

        ((DefaultListModel) (actionList.getModel())).remove(actionList.getSelectedIndex());
    }//GEN-LAST:event_removeActionButtonActionPerformed

    public void labelReleased(MouseEvent evt) {
    }

    public void labelDragged(MouseEvent evt) {
        if (resizeOperation) {
            JLabel object = (JLabel) evt.getSource();
            Point p = object.getParent().getMousePosition();
            if (p != null) {
                MediaObject mo;
                switch (resizeDirection) {
                    case Settings.RESIZE_N:
                        object.setSize(new Dimension(object.getWidth(), object.getLocation().y - p.y + object.getHeight()));
                        object.setLocation(object.getLocation().x, p.y);
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_S:
                        object.setSize(new Dimension(object.getWidth(), p.y - object.getLocation().y));
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_W:
                        object.setSize(new Dimension(object.getLocation().x - p.x + object.getWidth(), object.getHeight()));
                        object.setLocation(p.x, object.getLocation().y);
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_E:
                        object.setSize(new Dimension(p.x - object.getLocation().x, object.getHeight()));
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_NE:
                        object.setSize(new Dimension(p.x - object.getLocation().x, object.getLocation().y - p.y + object.getHeight()));
                        object.setLocation(object.getLocation().x, p.y);
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_NW:
                        object.setSize(new Dimension(object.getLocation().x - p.x + object.getWidth(), object.getLocation().y - p.y + object.getHeight()));
                        object.setLocation(p.x, p.y);
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_SE:
                        object.setSize(new Dimension(p.x - object.getLocation().x, p.y - object.getLocation().y));
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());
                        }
                        break;
                    case Settings.RESIZE_SW:
                        object.setSize(new Dimension(object.getLocation().x - p.x + object.getWidth(), p.y - object.getLocation().y));
                        object.setLocation(p.x, object.getLocation().y);
                        mo = Data.getData().get(object);
                        if (mo instanceof Image) {
                            ImageIcon icon = new ImageIcon(((Image) mo).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Video) {
                            Settings.FRAME_RESIZE_WIDTH = object.getWidth();
                            Settings.FRAME_RESIZE_HEIGHT = object.getHeight();
                            ImageIcon icon = new ImageIcon(((Video) mo).getImages().get(Settings.FRAME_NUM).getImage().getScaledInstance(object.getWidth(), object.getHeight(), java.awt.Image.SCALE_SMOOTH));
                            object.setIcon(icon);
                        } else if (mo instanceof Track) {
                            ((Track) (mo)).setWidth(object.getWidth());
                            ((Track) (mo)).setHeight(object.getHeight());


                        }
                        break;
                    default:
                        System.err.println("resize direction not specified");
                        return;
                }
            }
        } else {
            JLabel object = (JLabel) evt.getSource();
            Point p = object.getParent().getMousePosition();
            if (p != null) {
                int x = p.x - object.getWidth() / 2;
                int y = p.y - object.getHeight() / 2;

                x = (x > 0) ? x : 0;
                y = (y > 0) ? y : 0;
                object.setLocation(x, y);

                MediaObject mo = Data.getData().get(object);

                if (mo instanceof Track) {
                    KeyFrame frame = new KeyFrame();
                    frame.setFrameNum(Settings.FRAME_NUM);
                    frame.setPosition_x(object.getLocation().x);
                    frame.setPosition_y(object.getLocation().y);

                    ((Track) mo).addKeyFrame(frame);
                }
            }
        }
    }

    public void labelMoved(MouseEvent evt) {
        JLabel label = (JLabel) evt.getSource();
        JPanel panel = (JPanel) label.getParent();
        Point mouse_position = label.getParent().getMousePosition();
        Point label_position = label.getLocation();
        resizeOperation = true;
        if (mouse_position != null && label_position
                != null) {
            if ((mouse_position.y - label_position.y) < Settings.RESIZE_THRESHOLD) {
                //upper part
                if ((mouse_position.x - label_position.x) < Settings.RESIZE_THRESHOLD) {
                    //north-west cursor
                    panel.setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR));
                    this.resizeDirection = Settings.RESIZE_NW;
                } else if ((label_position.x + label.getWidth() - mouse_position.x) < Settings.RESIZE_THRESHOLD) {
                    //north-east cursor
                    panel.setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR));
                    this.resizeDirection = Settings.RESIZE_NE;
                } else {
                    //north cursor
                    panel.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
                    this.resizeDirection = Settings.RESIZE_N;
                }
            } else if ((label_position.y + label.getHeight() - mouse_position.y) < Settings.RESIZE_THRESHOLD) {
                //lower part
                if ((mouse_position.x - label_position.x) < Settings.RESIZE_THRESHOLD) {
                    //south-west cursor
                    panel.setCursor(new Cursor(Cursor.SW_RESIZE_CURSOR));
                    this.resizeDirection = Settings.RESIZE_SW;
                } else if ((label_position.x + label.getWidth() - mouse_position.x) < Settings.RESIZE_THRESHOLD) {
                    //south-east cursor
                    panel.setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR));
                    this.resizeDirection = Settings.RESIZE_SE;
                } else {
                    //south cursor
                    panel.setCursor(new Cursor(Cursor.S_RESIZE_CURSOR));
                    this.resizeDirection = Settings.RESIZE_S;
                }
            } else if ((mouse_position.x - label_position.x) < Settings.RESIZE_THRESHOLD) {
                //west resize cursor
                panel.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
                this.resizeDirection = Settings.RESIZE_W;
            } else if ((label_position.x + label.getWidth() - mouse_position.x) < Settings.RESIZE_THRESHOLD) {
                //east resize cursor
                panel.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
                this.resizeDirection = Settings.RESIZE_E;
            } else {
                //not resize
                resizeOperation = false;
                panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        } else {
            resizeOperation = false;
            panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
    }

    public void labelClicked(MouseEvent evt) {
        selectedLabel = (JLabel) evt.getSource();
        MediaObject object = Data.getData().get(selectedLabel);

        ArrayList actions = object.getActions();
        ((DefaultListModel) (actionList.getModel())).removeAllElements();
        for (int i = 0; i < actions.size(); i++) {
            ((DefaultListModel) (actionList.getModel())).addElement(actions.get(i));
        }
        if (Data.getData().get(selectedLabel).getName().length() <= 18) {
            selected.setText(Data.getData().get(selectedLabel).getName());
        } else {
            selected.setText(Data.getData().get(selectedLabel).getName().substring(0, 15) + "...");
        }
    }

    public void updateFrame() {
        fpsTextField.setText(String.valueOf(Settings.FPS));
        frameNumTextField.setText(String.valueOf(Settings.FRAME_NUM));
        timeline.setValue(Settings.FRAME_NUM);

        //first update video
        if (Data.getVideo() != null) {
            Image image = Data.getVideo().getImages().get(Settings.FRAME_NUM - 1);
            ImageIcon imageicon = null;
            if ((Data.getVideo().getStartFrame() <= 0) || (Data.getVideo().getStartFrame() <= Settings.FRAME_NUM && Data.getVideo().getEndFrame() >= Settings.FRAME_NUM)) {
                Data.getDisplay().get(Data.getVideo()).setVisible(true);
                if (image.getWidth() != Data.getDisplay().get(Data.getVideo()).getWidth() || image.getHeight() != Data.getDisplay().get(Data.getVideo()).getHeight()) {

                    BufferedImage before = (BufferedImage) image.getImage();
                    int w = Data.getDisplay().get(Data.getVideo()).getWidth();
                    int h = Data.getDisplay().get(Data.getVideo()).getHeight();
                    BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                    AffineTransform at = new AffineTransform();
                    at.scale((double) w / (double) image.getWidth(), (double) h / (double) image.getHeight());
                    AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
                    after = scaleOp.filter(before, after);

                    imageicon = new ImageIcon(after);
                } else {
                    imageicon = new ImageIcon(image.getImage());
                }
                Data.getDisplay().get(Data.getVideo()).setIcon(imageicon);
            } else {
                Data.getDisplay().get(Data.getVideo()).setVisible(false);
            }
        }

        //then update images
        for (int i = 0; i < Data.getImages().size(); i++) {
            Image dimage = Data.getImages().get(i);
            if (dimage.getStartFrame() >= 0) {
                if (dimage.getStartFrame() <= Settings.FRAME_NUM && dimage.getEndFrame() >= Settings.FRAME_NUM) {
                    Data.getDisplay().get(dimage).setVisible(true);
                } else {
                    Data.getDisplay().get(dimage).setVisible(false);
                }
            }
        }

        //then update tracks
        for (int i = 0; i < Data.getTracks().size(); i++) {
            Track track = Data.getTracks().get(i);
            for (int j = 0; j < track.getKeyframes().size(); j++) {
                System.out.println("keyframe " + j + ":" + track.getKeyframes().get(j).toString());
            }
            if (track.getStartFrame() >= 0) {
                if (track.getStartFrame() <= Settings.FRAME_NUM && track.getEndFrame() >= Settings.FRAME_NUM) {
                    Data.getDisplay().get(track).setVisible(true);
                    Point p = track.getLocation(Settings.FRAME_NUM);
                    Data.getDisplay().get(track).setLocation(p);
                    System.out.println("visiable1");
                    System.out.println(p.toString());
                } else {
                    System.out.println("invisiable");
                    Data.getDisplay().get(track).setVisible(false);
                }
            } else {
                Data.getDisplay().get(track).setVisible(true);
                Point p = track.getLocation(Settings.FRAME_NUM);
                Data.getDisplay().get(track).setLocation(p);
                System.out.println("visiable2");
                System.out.println(p.toString());
            }
        }

        fpsTextField.setText(String.valueOf(Settings.FPS));
        frameNumTextField.setText(String.valueOf(Settings.FRAME_NUM));
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainFrame().setVisible(true);
            }
        });

    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JList actionList;
    private javax.swing.JButton addDisplayActionButton;
    private javax.swing.JButton addLinkActionButton;
    private javax.swing.JButton addPauseActionButton;
    private javax.swing.JButton addPlayActionButton;
    private javax.swing.JButton addStopActionButton;
    private javax.swing.JFileChooser audioFileChooser;
    private javax.swing.JPanel canvasBack;
    private javax.swing.JPanel canvasPanel;
    private javax.swing.JMenuItem canvasjMenuItem;
    private javax.swing.JPanel controlPanel;
    private javax.swing.JMenuItem exitJMenuItem;
    private javax.swing.JTextField fpsTextField;
    private javax.swing.JTextField frameNumTextField;
    private javax.swing.JButton framePauseButton;
    private javax.swing.JButton framePlayButton;
    private javax.swing.JButton frameStopButton;
    private javax.swing.JFileChooser imageFileChooser;
    private javax.swing.JPanel infoPanel;
    private javax.swing.JMenuItem insertAudioJMenuItem;
    private javax.swing.JMenuItem insertImageJMenuItem;
    private javax.swing.JMenuItem insertTTrackAreaJMenuItem;
    private javax.swing.JMenuItem insertVideoJMenuItem;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JPopupMenu.Separator jSeparator4;
    private javax.swing.JSeparator jSeparator5;
    private javax.swing.JList libraryList;
    private javax.swing.JFileChooser mainFileChooser;
    private javax.swing.JMenuItem newJMenuItem;
    private javax.swing.JMenuItem openJMenuItem;
    private javax.swing.JButton publishButton;
    private javax.swing.JFileChooser publishFile;
    private javax.swing.JButton removeActionButton;
    private javax.swing.JMenuItem saveJMenuItem;
    private javax.swing.JLabel selected;
    private javax.swing.JSlider timeline;
    private javax.swing.JFileChooser videoFileChooser;
    // End of variables declaration//GEN-END:variables
    private ImportDialog importVideoDialog;
    private boolean resizeOperation;
    private int resizeDirection;
    private JLabel selectedLabel;

    class ImportAudioTask extends SwingWorker<Void, Void> {

        private String filaname;
        private String filepath;

        @Override
        protected Void doInBackground() throws Exception {
            if (filepath == null || filaname == null) {
                System.err.println("filepath or filename null");
                return null;
            }
            System.out.println("do in background");
            LoadingMonitor.LOAD_SIZE = 0;
            Audio audio = MediaFactory.getInstance().readAudio(filepath, filaname, Settings.AUDIO_TYPE_WAV);
            Data.setAudio(audio);
            ((DefaultListModel) (libraryList.getModel())).addElement(audio.getFilename());

            Settings.IS_AUDIO_IMPORTED = true;
            new Thread() {

                @Override
                public void run() {
                    Data.getAudio().load();
                }
            }.start();
            return null;
            //  Data.getAudio().load();
        }

        @Override
        protected void done() {
            //Settings.TOTAL_FRAME_NUM;
            if (!Settings.IS_VIDEO_IMPORTED) {
                timeline.setMaximum(Data.getAudio().getf() / 1000);
                timeline.setMajorTickSpacing(10137);
                timeline.setMinorTickSpacing(1014);
            }
            // return null;
        }

        public String getFilaname() {
            return filaname;
        }

        public void setFilaname(String filaname) {
            this.filaname = filaname;
        }

        public String getFilepath() {
            return filepath;
        }

        public void setFilepath(String filepath) {
            this.filepath = filepath;
        }
    }

    class ImportVideoTask extends SwingWorker<Void, Void> {

        private String filaname;
        private String filepath;

        @Override
        protected Void doInBackground() throws Exception {

            if (filepath == null || filaname == null) {
                System.err.println("filepath or filename null");
                return null;
            }

            LoadingMonitor.LOAD_SIZE = 0;

            Video video = MediaFactory.getInstance().readVideo(filepath, filaname, Settings.VIDEO_DEFAULT_WIDTH, Settings.VIDEO_DEFAULT_HEIGHT);
            Data.setVideo(video);
            Data.getVideo().prepare();

            new Thread() {

                @Override
                public void run() {
                    Data.getVideo().load();
                }
            }.start();

            while (LoadingMonitor.LOAD_SIZE < LoadingMonitor.TOTAL_SIZE || !LoadingMonitor.LOAD_FINISHED) {
                if (!LoadingMonitor.LOAD_FINISHED) {
                    int progress = (int) (LoadingMonitor.LOAD_SIZE / LoadingMonitor.TOTAL_SIZE * 100);
                    setProgress(progress);
                }
            }
            return null;
        }

        @Override
        public void done() {
            if (Data.getVideo() != null && Data.getVideo().getImages() != null) {
                Toolkit.getDefaultToolkit().beep();
                ((DefaultListModel) (libraryList.getModel())).addElement(Data.getVideo().getFilename());

                timeline.setMinimum(1);
                timeline.setMaximum(Data.getVideo().getImages().size());

                timeline.setMajorTickSpacing(Data.getVideo().getImages().size() / 10);
                timeline.setMinorTickSpacing(Data.getVideo().getImages().size() / 100);

                ImageIcon firstImage = new ImageIcon(Data.getVideo().getImages().get(0).getImage());

                frameNumTextField.setText("1");
                Settings.FRAME_NUM = 1;

                JLabel videoLabel = new JLabel();
                videoLabel.setIcon(firstImage);
                videoLabel.setBorder(BorderFactory.createLineBorder(Color.black));
                videoLabel.setSize(new Dimension(Settings.VIDEO_DEFAULT_WIDTH, Settings.VIDEO_DEFAULT_HEIGHT));
                videoLabel.addMouseMotionListener(new MouseMotionListener() {

                    public void mouseDragged(MouseEvent me) {
                        labelDragged(me);
                    }

                    public void mouseMoved(MouseEvent me) {
                        labelMoved(me);
                    }
                });
                videoLabel.addMouseListener(new MouseListener() {

                    public void mouseClicked(MouseEvent me) {
                        labelClicked(me);
                    }

                    public void mousePressed(MouseEvent me) {
                    }

                    public void mouseReleased(MouseEvent me) {
                        labelReleased(me);
                    }

                    public void mouseEntered(MouseEvent me) {
                    }

                    public void mouseExited(MouseEvent me) {
                    }
                });

                Data.getDisplay().put(Data.getVideo(), videoLabel);
                Data.getData().put(videoLabel, Data.getVideo());


                canvasPanel.add(videoLabel);
                canvasPanel.setComponentZOrder(videoLabel, 0);
                canvasPanel.validate();
                canvasPanel.repaint();

                Settings.IS_VIDEO_IMPORTED = true;
                Settings.TOTAL_FRAME_NUM = Data.getVideo().getImages().size();

                for (int i = 0; i < Data.getImages().size(); i++) {
                    Data.getImages().get(i).setStartFrame(1);
                    Data.getImages().get(i).setEndFrame(Settings.TOTAL_FRAME_NUM);
                }

                importVideoDialog.setVisible(false);
            }
        }

        public String getFilaname() {
            return filaname;
        }

        public void setFilaname(String filaname) {
            this.filaname = filaname;
        }

        public String getFilepath() {
            return filepath;
        }

        public void setFilepath(String filepath) {
            this.filepath = filepath;
        }
    }

    class FrameUpdateThread extends Thread {

        Video video;
        JLabel label;

        @Override
        public void run() {
            video = Data.getVideo();
            label = Data.getDisplay().get(video);
            while (Settings.IS_PLAYING) {
                try {
                    if (Settings.FRAME_NUM < 0 || Settings.FRAME_NUM > timeline.getMaximum()) {
                        Settings.FRAME_NUM = 1;
                        updateFrame();
                        Settings.IS_PLAYING = false;
                        continue;
                    }
                    updateFrame();
                    if (Settings.IS_AUDIO_IMPORTED) {
                        double rate1 = (double) Data.getAudio().getf() / (double) Data.getImages().size();
                        double real_rate1 = (double) Data.getAudio().getPos() / Settings.FRAME_NUM;
                        if (real_rate1 < 0.99) {
                            System.out.println("real_rate1 < 0.99");
                        } else {
                            Settings.FRAME_NUM++;
                        }
                    } else {
                        Settings.FRAME_NUM++;
                    }
                    Thread.sleep(1000 / 30);
                } catch (InterruptedException ex) {
                    Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}
